<!DOCTYPE html>
<html>

<head>
  <title>Quarkus - Measuring the coverage of your tests</title>
  <script id="adobe_dtm" src="https://www.redhat.com/dtm.js" type="text/javascript"></script>
  <script src="/assets/javascript/highlight.pack.js" type="text/javascript"></script>
  <META HTTP-EQUIV='Content-Security-Policy' CONTENT="default-src 'none'; script-src 'self' 'unsafe-eval' 'sha256-ANpuoVzuSex6VhqpYgsG25OHWVA1I+F6aGU04LoI+5s=' 'sha256-ipy9P/3rZZW06mTLAR0EnXvxSNcnfSDPLDuh3kzbB1w=' js.bizographics.com https://www.redhat.com assets.adobedtm.com jsonip.com https://ajax.googleapis.com https://www.googletagmanager.com https://www.google-analytics.com https://use.fontawesome.com; style-src 'self' https://fonts.googleapis.com https://use.fontawesome.com; img-src 'self' *; media-src 'self' ; frame-src https://www.googletagmanager.com https://www.youtube.com; frame-ancestors 'none'; base-uri 'none'; object-src 'none'; form-action 'none'; font-src 'self' https://use.fontawesome.com https://fonts.gstatic.com;">
  <META HTTP-EQUIV='X-Frame-Options' CONTENT="DENY">
  <META HTTP-EQUIV='X-XSS-Protection' CONTENT="1; mode=block">
  <META HTTP-EQUIV='X-Content-Type-Options' CONTENT="nosniff">
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="description" content="Quarkus: Supersonic Subatomic Java">
  <meta name="twitter:card" content="summary_large_image">
  <meta name="twitter:site" content="@QuarkusIO"> 
  <meta name="twitter:creator" content="@QuarkusIO">
  <meta property="og:url" content="https://quarkus.io/guides/tests-with-coverage" />
  <meta property="og:title" content="Quarkus - Measuring the coverage of your tests" />
  <meta property="og:description" content="Quarkus: Supersonic Subatomic Java" />
  <meta property="og:image" content="/assets/images/quarkus_card.png" />
  <link rel="canonical" href="https://quarkus.io/guides/tests-with-coverage">
  <link rel="shortcut icon" type="image/png" href="/favicon.ico" >
  <link rel="stylesheet" href="https://quarkus.io/guides/stylesheet/config.css" />
  <link rel="stylesheet" href="/assets/css/main.css" />
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css" integrity="sha384-lKuwvrZot6UHsBSfcMvOkWwlCMgc0TaWr+30HWe3a4ltaBwTZhyTEggF5tJv8tbt" crossorigin="anonymous">
  <link rel="alternate" type="application/rss+xml"  href="https://quarkus.io/feed.xml" title="Quarkus">
  <script src="https://quarkus.io/assets/javascript/goan.js" type="text/javascript"></script>
  <script src="https://quarkus.io/assets/javascript/hl.js" type="text/javascript"></script>
</head>

<body class="guides">
  <!-- Google Tag Manager (noscript) -->
  <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-NJWS5L"
  height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
  <!-- End Google Tag Manager (noscript) -->

  <div class="nav-wrapper">
  <div class="grid-wrapper">
    <div class="width-12-12">
      <input type="checkbox" id="checkbox" />
      <nav id="main-nav" class="main-nav">
  <div class="container">
    <div class="logo-wrapper">
      
        <a href="/"><img src="/assets/images/quarkus_logo_horizontal_rgb_600px_reverse.png" class="project-logo" title="Quarkus"></a>
      
    </div>
    <label class="nav-toggle" for="checkbox">
      <i class="fa fa-bars"></i>
    </label>
    <div id="menu" class="menu">
      <span>
        <a href="/get-started/" class="">Get Started</a>
      </span>
      <span>
        <a href="/guides/" class="active">Guides</a>
      </span>
      <span>
        <a href="/community/" class="">Community</a>
      </span>
      <span>
        <a href="/support/" class="">Support</a>
      </span>
      <span>
        <a href="/blog/" class="">Blog</a>
      </span>
      <span>
        <a href="https://code.quarkus.io" class="button-cta secondary white">Start Coding</a>
      </span>
    </div>
  </div>
      </nav>
    </div>
  </div>
</div>

  <div class="content">
    <div class="guide">
  <div class="width-12-12">
    <h1 class="text-caps">Quarkus - Measuring the coverage of your tests</h1>
    <div class="hide-mobile toc"><ul class="sectlevel1">
<li><a href="#prerequisites">1. Prerequisites</a></li>
<li><a href="#architecture">2. Architecture</a></li>
<li><a href="#solution">3. Solution</a></li>
<li><a href="#starting-from-a-simple-project-and-two-tests">4. Starting from a simple project and two tests</a></li>
<li><a href="#separating-executions-of-unit-tests-and-integration-tests">5. Separating executions of Unit Tests and Integration Tests</a></li>
<li><a href="#measuring-the-coverage-of-junit-tests-using-jacoco">6. Measuring the coverage of JUnit tests using JaCoCo</a></li>
<li><a href="#measuring-separately-the-coverage-of-each-test-type">7. Measuring separately the coverage of each test type</a></li>
<li><a href="#the-coverage-does-not-seem-to-correspond-to-the-reality">8. The coverage does not seem to correspond to the reality</a></li>
<li><a href="#instrumenting-the-classes-instead">9. Instrumenting the classes instead</a></li>
<li><a href="#bonus-building-a-consolidated-report-for-unit-tests-and-integration-tests">10. Bonus: Building a consolidated report for Unit Tests and Integration Tests</a></li>
<li><a href="#conclusion">11. Conclusion</a></li>
</ul></div>
    <div>
      <div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>Learn how to measure the test coverage of your application. This guide covers:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Measuring the coverage of your Unit Tests</p>
</li>
<li>
<p>Measuring the coverage of your Integration Tests</p>
</li>
<li>
<p>Separating the execution of your Unit Tests and Integration Tests</p>
</li>
<li>
<p>Consolidating the coverage for all your tests</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Please note that code coverage is not supported in native mode.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="prerequisites"><a class="anchor" href="#prerequisites"></a>1. Prerequisites</h2>
<div class="sectionbody">
<div class="paragraph">
<p>To complete this guide, you need:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>less than 15 minutes</p>
</li>
<li>
<p>an IDE</p>
</li>
<li>
<p>JDK 1.8+ installed with JAVA_HOME configured appropriately</p>
</li>
<li>
<p>Apache Maven 3.6.2+</p>
</li>
<li>
<p>Having completed the <a href="https://quarkus.io/guides/getting-started-testing">Testing your application guide</a></p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="architecture"><a class="anchor" href="#architecture"></a>2. Architecture</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The application built in this guide is just a JAX-RS endpoint (hello world) that relies on dependency injection to use a service.
The service will be tested with JUnit 5 and the endpoint will be annotated via a <code>@QuarkusTest</code> annotation.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="solution"><a class="anchor" href="#solution"></a>3. Solution</h2>
<div class="sectionbody">
<div class="paragraph">
<p>We recommend that you follow the instructions in the next sections and create the application step by step. However, you can go right to the completed example.
Clone the Git repository: <code>git clone <a href="https://github.com/quarkusio/quarkus-quickstarts.git" class="bare">https://github.com/quarkusio/quarkus-quickstarts.git</a></code>, or download an <a href="https://github.com/quarkusio/quarkus-quickstarts/archive/master.zip">archive</a>.</p>
</div>
<div class="paragraph">
<p>The solution is located in the <code>tests-with-coverage-quickstart</code> <a href="https://github.com/quarkusio/quarkus-quickstarts/tree/master/tests-with-coverage-quickstart">directory</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="starting-from-a-simple-project-and-two-tests"><a class="anchor" href="#starting-from-a-simple-project-and-two-tests"></a>4. Starting from a simple project and two tests</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Let&#8217;s start from an empty application created with the Quarkus Maven plugin:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">mvn io.quarkus:quarkus-maven-plugin:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=tests-with-coverage-quickstart
cd tests-with-coverage-quickstart</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now we&#8217;ll be adding all the elements necessary to have an application that is properly covered with tests.</p>
</div>
<div class="paragraph">
<p>First, an application serving a hello endpoint:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">package org.acme.testcoverage;

import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/hello")
public class GreetingResource {

    private final GreetingService service;

    @Inject
    public GreetingResource(GreetingService service) {
        this.service = service;
    }

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    @Path("/greeting/{name}")
    public String greeting(@PathParam("name") String name) {
        return service.greeting(name);
    }

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return "hello";
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>This endpoint uses a greeting service:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">package org.acme.testcoverage;

import javax.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class GreetingService {

    public String greeting(String name) {
        return "hello " + name;
    }

}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The project will also need some tests. First a simple JUnit:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">package org.acme.testcoverage;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

public class GreetingServiceTest {

    @Test
    public void testGreetingService() {
        GreetingService service = new GreetingService();
        Assertions.assertEquals("hello Quarkus", service.greeting("Quarkus"));
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>But also a <code>@QuarkusTest</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">package org.acme.testcoverage;

import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Tag;

import java.util.UUID;

import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.is;

@QuarkusTest
@Tag("integration")
public class GreetingResourceTest {

    @Test
    public void testHelloEndpoint() {
        given()
          .when().get("/hello")
          .then()
             .statusCode(200)
             .body(is("hello"));
    }

    @Test
    public void testGreetingEndpoint() {
        String uuid = UUID.randomUUID().toString();
        given()
          .pathParam("name", uuid)
          .when().get("/hello/greeting/{name}")
          .then()
            .statusCode(200)
            .body(is("hello " + uuid));
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The first one will be our example of a Unit Test and the second one will be our example of Integration Test.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="separating-executions-of-unit-tests-and-integration-tests"><a class="anchor" href="#separating-executions-of-unit-tests-and-integration-tests"></a>5. Separating executions of Unit Tests and Integration Tests</h2>
<div class="sectionbody">
<div class="paragraph">
<p>You may want to consider that JUnits and QuarkusTests are two different kind of tests and that they deserve to be separated. This way you could run them separately, in different cases or some more often than the others.
In order to do so, we&#8217;ll use a feature of JUnit 5 that allows us to tag some tests. Let&#8217;s tag <code>GreetingResourceTest.java</code> and specify that it is an Integration Test:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">import org.junit.jupiter.api.Tag;
...

@QuarkusTest
@Tag("integration")
public class GreetingResourceTest {
    ...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>We&#8217;re now able to distinguish unit tests and integration tests. Now, let&#8217;s bind them to different Maven lifecycle phases. Let&#8217;s use surefire to bind unit tests to the <strong>test</strong> phase and the integration tests to the <strong>integration-test</strong> phase.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="xml" class="language-xml hljs">&lt;project&gt;
    ...
    &lt;build&gt;
        &lt;plugins&gt;
            &lt;plugin&gt;
                &lt;artifactId&gt;maven-surefire-plugin&lt;/artifactId&gt;
                &lt;version&gt;${surefire-plugin.version}&lt;/version&gt;
                &lt;configuration&gt;
                    &lt;excludedGroups&gt;integration&lt;/excludedGroups&gt;
                    &lt;systemPropertyVariables&gt;
                        &lt;java.util.logging.manager&gt;org.jboss.logmanager.LogManager&lt;/java.util.logging.manager&gt;
                        &lt;maven.home&gt;${maven.home}&lt;/maven.home&gt;
                    &lt;/systemPropertyVariables&gt;
                &lt;/configuration&gt;
                &lt;executions&gt;
                    &lt;execution&gt;
                        &lt;id&gt;integration-tests&lt;/id&gt;
                        &lt;phase&gt;integration-test&lt;/phase&gt;
                        &lt;goals&gt;
                            &lt;goal&gt;test&lt;/goal&gt;
                        &lt;/goals&gt;
                        &lt;configuration&gt;
                            &lt;excludedGroups&gt;!integration&lt;/excludedGroups&gt;
                            &lt;groups&gt;integration&lt;/groups&gt;
                        &lt;/configuration&gt;
                    &lt;/execution&gt;
                &lt;/executions&gt;
            &lt;/plugin&gt;
        &lt;/plugins&gt;
    &lt;/build&gt;
    ...
&lt;/project&gt;</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
This way, the <code>QuarkusTest</code> instances will be executed as part of the <code>integration-test</code> build phase while the other JUnit tests will still be ran during the <code>test</code> phase.
You can run all the tests with the command <code>./mvnw clean verify</code> (and you will notice that two tests are ran in different phases).
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="measuring-the-coverage-of-junit-tests-using-jacoco"><a class="anchor" href="#measuring-the-coverage-of-junit-tests-using-jacoco"></a>6. Measuring the coverage of JUnit tests using JaCoCo</h2>
<div class="sectionbody">
<div class="paragraph">
<p>It is now time to introduce JaCoCo to measure the coverage. The straightforward way to add JaCoCo to your build is to reference the plugin in your <code>pom.xml</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="xml" class="language-xml hljs">    &lt;properties&gt;
    ...
        &lt;jacoco.version&gt;0.8.4&lt;/jacoco.version&gt;
    &lt;/properties&gt;

    &lt;build&gt;
        &lt;plugins&gt;
        ...
            &lt;plugin&gt;
                &lt;groupId&gt;org.jacoco&lt;/groupId&gt;
                &lt;artifactId&gt;jacoco-maven-plugin&lt;/artifactId&gt;
                &lt;version&gt;${jacoco.version}&lt;/version&gt;
                &lt;executions&gt;
                    &lt;execution&gt;
                        &lt;id&gt;default-prepare-agent&lt;/id&gt;
                        &lt;goals&gt;
                            &lt;goal&gt;prepare-agent&lt;/goal&gt;
                        &lt;/goals&gt;
                    &lt;/execution&gt;
                    &lt;execution&gt;
                        &lt;id&gt;default-report&lt;/id&gt;
                        &lt;goals&gt;
                            &lt;goal&gt;report&lt;/goal&gt;
                        &lt;/goals&gt;
                        &lt;configuration&gt;
                            &lt;dataFile&gt;${project.build.directory}/jacoco.exec&lt;/dataFile&gt;
                            &lt;outputDirectory&gt;${project.reporting.outputDirectory}/jacoco&lt;/outputDirectory&gt;
                        &lt;/configuration&gt;
                    &lt;/execution&gt;
                &lt;/executions&gt;
            &lt;/plugin&gt;
        &lt;/plugins&gt;
    &lt;/build&gt;</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
If you run <code>./mvnw clean test</code> the coverage information will be collected during the execution of the unit tests in the file <code>jacoco.exec</code>.
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="measuring-separately-the-coverage-of-each-test-type"><a class="anchor" href="#measuring-separately-the-coverage-of-each-test-type"></a>7. Measuring separately the coverage of each test type</h2>
<div class="sectionbody">
<div class="paragraph">
<p>It is not strictly necessary, but let&#8217;s distinguish the coverage brought by each test type. To do so, we`ll just output the coverage info in two different files, one in <code>jacoco-ut.exec</code> and one in <code>jacoco-it.exec</code>.
We also need to generate a separate report for each test execution. Let&#8217;s adjust the Jacoco configuration for that:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="xml" class="language-xml hljs">    &lt;properties&gt;
    ...
        &lt;jacoco.version&gt;0.8.4&lt;/jacoco.version&gt;
    &lt;/properties&gt;

    &lt;build&gt;
        &lt;plugins&gt;
        ...
            &lt;plugin&gt;
                &lt;groupId&gt;org.jacoco&lt;/groupId&gt;
                &lt;artifactId&gt;jacoco-maven-plugin&lt;/artifactId&gt;
                &lt;version&gt;${jacoco.version}&lt;/version&gt;
                &lt;executions&gt;
                    &lt;execution&gt;
                        &lt;id&gt;prepare-agent-ut&lt;/id&gt;
                        &lt;goals&gt;
                            &lt;goal&gt;prepare-agent&lt;/goal&gt;
                        &lt;/goals&gt;
                        &lt;configuration&gt;
                            &lt;destFile&gt;${project.build.directory}/jacoco-ut.exec&lt;/destFile&gt;
                        &lt;/configuration&gt;
                    &lt;/execution&gt;
                    &lt;execution&gt;
                        &lt;id&gt;prepare-agent-it&lt;/id&gt;
                        &lt;phase&gt;pre-integration-test&lt;/phase&gt;
                        &lt;goals&gt;
                            &lt;goal&gt;prepare-agent&lt;/goal&gt;
                        &lt;/goals&gt;
                        &lt;configuration&gt;
                            &lt;destFile&gt;${project.build.directory}/jacoco-it.exec&lt;/destFile&gt;
                        &lt;/configuration&gt;
                    &lt;/execution&gt;
                    &lt;execution&gt;
                        &lt;id&gt;report-ut&lt;/id&gt;
                        &lt;goals&gt;
                            &lt;goal&gt;report&lt;/goal&gt;
                        &lt;/goals&gt;
                        &lt;configuration&gt;
                            &lt;dataFile&gt;${project.build.directory}/jacoco-ut.exec&lt;/dataFile&gt;
                            &lt;outputDirectory&gt;${project.reporting.outputDirectory}/jacoco-ut&lt;/outputDirectory&gt;
                        &lt;/configuration&gt;
                    &lt;/execution&gt;
                    &lt;execution&gt;
                        &lt;id&gt;report-it&lt;/id&gt;
                        &lt;phase&gt;post-integration-test&lt;/phase&gt;
                        &lt;goals&gt;
                            &lt;goal&gt;report&lt;/goal&gt;
                        &lt;/goals&gt;
                        &lt;configuration&gt;
                            &lt;dataFile&gt;${project.build.directory}/jacoco-it.exec&lt;/dataFile&gt;
                            &lt;outputDirectory&gt;${project.reporting.outputDirectory}/jacoco-it&lt;/outputDirectory&gt;
                        &lt;/configuration&gt;
                    &lt;/execution&gt;
                &lt;/executions&gt;
            &lt;/plugin&gt;
        &lt;/plugins&gt;
    &lt;/build&gt;</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="the-coverage-does-not-seem-to-correspond-to-the-reality"><a class="anchor" href="#the-coverage-does-not-seem-to-correspond-to-the-reality"></a>8. The coverage does not seem to correspond to the reality</h2>
<div class="sectionbody">
<div class="paragraph">
<p>You can now run the tests: <code>./mvnw clean verify</code> As explained earlier, it will run the unit tests first, then the integration tests. And finally, it will generate two separate reports. First a report of the coverage of the unit tests in <code>target/site/jacoco-ut</code> then a report of the coverage of the integration tests in <code>target/site/jacoco-it</code>.</p>
</div>
<div class="paragraph">
<p>Given the content of <code>GreetingResourceTest</code>, <code>GreetingResource</code> should have been covered. But when we open the report <code>target/site/jacoco-it/index.html</code>, the class <code>GreetingResource</code> is reported with 0% of coverage. But the fact that <code>GreetingService</code> is reported as covered shows that the test execution was actually recorded. How come?</p>
</div>
<div class="paragraph">
<p>During the report generation, you may have noticed a warning:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">[WARNING] Classes in bundle '***' do no match with execution data. For report generation the same class files must be used as at runtime.
[WARNING] Execution data for class org/acme/testcoverage/GreetingResource does not match.</code></pre>
</div>
</div>
<div class="paragraph">
<p>It seems that Quarkus and JaCoCo step on each other&#8217;s toes. What happens is that Quarkus transforms the JAX-RS resources (and also the Panache files).
You may have noticed that <code>GreetingResource</code> was not written in the simplest way like:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">...
@Path("/hello")
public class GreetingResource {

    @Inject
    GreetingService service;

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    @Path("/greeting/{name}")
    public String greeting(@PathParam("name") String name) {
        return service.greeting(name);
    }

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return "hello";
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Above, the constructor is implicit and we use injection to have an instance of <code>GreetingService</code>. Note that, with this code relying on an implicit constructor, the coverage would have been reported properly by JaCoCo.
Instead, we introduced a constructor based injection:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">...
@Path("/hello")
public class GreetingResource {

    private final GreetingService service;

    @Inject
    public GreetingResource(GreetingService service) {
        this.service = service;
    }
...
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Some might say that this approach is preferable since the field can be <strong>final</strong> like this. Anyway, in some cases you might need an explicit constructor. And, in that case, the coverage is not reported properly by JaCoCo.
This is because Quarkus generates a constructor without any parameter and does some bycode manipulations in order to add it to the class. That is what happened here, just before the execution of the integration tests:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">[INFO] --- quarkus-maven-plugin:0.16.0:build (default) @ getting-started-testing ---
[INFO] [io.quarkus.deployment.QuarkusAugmentor] Beginning quarkus augmentation
...</code></pre>
</div>
</div>
<div class="paragraph">
<p>As a consequence, JaCoCo does not recognize the classes when it wants to create its report. But wait&#8230;&#8203; there is a solution.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="instrumenting-the-classes-instead"><a class="anchor" href="#instrumenting-the-classes-instead"></a>9. Instrumenting the classes instead</h2>
<div class="sectionbody">
<div class="paragraph">
<p>JaCoCo has two modes. The first one is based on an agent and instruments classes on-the-fly. Unfortunately, this is incompatible with the dynamic classfile transformations that Quarkus does. The second mode is called <a href="https://www.eclemma.org/jacoco/trunk/doc/offline.html">offline instrumentation</a>. Classes are pre-instrumented in advance via the <strong>jacoco:instrument</strong> Maven goal and during their usage (when the tests are ran), <strong>jacocoagent.jar</strong> must be added to the classpath.
Once the tests have been executed, it is recommended to restore the original classes using the <strong>jacoco:restore-instrumented-classes</strong> Maven goal.</p>
</div>
<div class="paragraph">
<p>Let&#8217;s first add the dependency on <strong>jacocoagent.jar</strong>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="xml" class="language-xml hljs">&lt;project&gt;
    ...
    &lt;dependencies&gt;
        ...
        &lt;dependency&gt;
            &lt;groupId&gt;org.jacoco&lt;/groupId&gt;
            &lt;artifactId&gt;org.jacoco.agent&lt;/artifactId&gt;
            &lt;classifier&gt;runtime&lt;/classifier&gt;
            &lt;scope&gt;test&lt;/scope&gt;
            &lt;version&gt;${jacoco.version}&lt;/version&gt;
        &lt;/dependency&gt;
    &lt;/dependencies&gt;
&lt;/project&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Then let&#8217;s configure three jacoco plugin goals for unit tests:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>One to instrument the classes during the <strong>process-classes</strong> phase</p>
</li>
<li>
<p>One to restore the original classes during the <strong>prepare-package</strong> phase (after the tests are ran)</p>
</li>
<li>
<p>One to generate the report during the <strong>verify</strong> phase (the report generation requires the original classes to have been restored)</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>and a similar setup for the integration tests too:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="xml" class="language-xml hljs">&lt;project&gt;
    ...
    &lt;build&gt;
        &lt;plugins&gt;
            ...
            &lt;plugin&gt;
                &lt;groupId&gt;org.jacoco&lt;/groupId&gt;
                &lt;artifactId&gt;jacoco-maven-plugin&lt;/artifactId&gt;
                &lt;version&gt;${jacoco.version}&lt;/version&gt;
                &lt;executions&gt;
                    &lt;execution&gt;
                        &lt;id&gt;instrument-ut&lt;/id&gt;
                        &lt;goals&gt;
                            &lt;goal&gt;instrument&lt;/goal&gt;
                        &lt;/goals&gt;
                    &lt;/execution&gt;
                    &lt;execution&gt;
                        &lt;id&gt;restore-ut&lt;/id&gt;
                        &lt;goals&gt;
                            &lt;goal&gt;restore-instrumented-classes&lt;/goal&gt;
                        &lt;/goals&gt;
                    &lt;/execution&gt;
                    &lt;execution&gt;
                        &lt;id&gt;report-ut&lt;/id&gt;
                        &lt;goals&gt;
                            &lt;goal&gt;report&lt;/goal&gt;
                        &lt;/goals&gt;
                        &lt;configuration&gt;
                            &lt;dataFile&gt;${project.build.directory}/jacoco-ut.exec&lt;/dataFile&gt;
                            &lt;outputDirectory&gt;${project.reporting.outputDirectory}/jacoco-ut&lt;/outputDirectory&gt;
                        &lt;/configuration&gt;
                    &lt;/execution&gt;
                    &lt;execution&gt;
                        &lt;id&gt;instrument-it&lt;/id&gt;
                        &lt;phase&gt;pre-integration-test&lt;/phase&gt;
                        &lt;goals&gt;
                            &lt;goal&gt;instrument&lt;/goal&gt;
                        &lt;/goals&gt;
                    &lt;/execution&gt;
                    &lt;execution&gt;
                        &lt;id&gt;restore-it&lt;/id&gt;
                        &lt;phase&gt;post-integration-test&lt;/phase&gt;
                        &lt;goals&gt;
                            &lt;goal&gt;restore-instrumented-classes&lt;/goal&gt;
                        &lt;/goals&gt;
                    &lt;/execution&gt;
                    &lt;execution&gt;
                        &lt;id&gt;report-it&lt;/id&gt;
                        &lt;phase&gt;post-integration-test&lt;/phase&gt;
                        &lt;goals&gt;
                            &lt;goal&gt;report&lt;/goal&gt;
                        &lt;/goals&gt;
                        &lt;configuration&gt;
                            &lt;dataFile&gt;${project.build.directory}/jacoco-it.exec&lt;/dataFile&gt;
                            &lt;outputDirectory&gt;${project.reporting.outputDirectory}/jacoco-it&lt;/outputDirectory&gt;
                        &lt;/configuration&gt;
                    &lt;/execution&gt;
                &lt;/executions&gt;
            &lt;/plugin&gt;
        &lt;/plugins&gt;
    &lt;/build&gt;
&lt;/project&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>It also requires a small change in the Surefire configuration. Note below that we specified <code>jacoco-agent.destfile</code> as a system property in the default case (unit tests) and for the integration tests.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="xml" class="language-xml hljs">&lt;project&gt;
    ...
    &lt;build&gt;
        &lt;plugins&gt;
            ...
            &lt;plugin&gt;
                &lt;artifactId&gt;maven-surefire-plugin&lt;/artifactId&gt;
                &lt;version&gt;${surefire-plugin.version}&lt;/version&gt;
                &lt;configuration&gt;
                    &lt;excludedGroups&gt;integration&lt;/excludedGroups&gt;
                    &lt;systemPropertyVariables&gt;
                        &lt;jacoco-agent.destfile&gt;${project.build.directory}/jacoco-ut.exec&lt;/jacoco-agent.destfile&gt;
                        &lt;java.util.logging.manager&gt;org.jboss.logmanager.LogManager&lt;/java.util.logging.manager&gt;
                        &lt;maven.home&gt;${maven.home}&lt;/maven.home&gt;
                    &lt;/systemPropertyVariables&gt;
                &lt;/configuration&gt;
                &lt;executions&gt;
                    &lt;execution&gt;
                        &lt;id&gt;integration-tests&lt;/id&gt;
                        &lt;phase&gt;integration-test&lt;/phase&gt;
                        &lt;goals&gt;
                            &lt;goal&gt;test&lt;/goal&gt;
                        &lt;/goals&gt;
                        &lt;configuration&gt;
                            &lt;excludedGroups&gt;!integration&lt;/excludedGroups&gt;
                            &lt;groups&gt;integration&lt;/groups&gt;
                            &lt;systemPropertyVariables&gt;
                                &lt;jacoco-agent.destfile&gt;${project.build.directory}/jacoco-it.exec&lt;/jacoco-agent.destfile&gt;
                            &lt;/systemPropertyVariables&gt;
                        &lt;/configuration&gt;
                    &lt;/execution&gt;
                &lt;/executions&gt;
            &lt;/plugin&gt;
        &lt;/plugins&gt;
    &lt;/build&gt;
&lt;/project&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Let&#8217;s now check the generated report that can be found in <code>target/site/jacoco-it/index.html</code>. The report now shows that <code>GreetingResource</code> is actually properly covered! Yay!</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="bonus-building-a-consolidated-report-for-unit-tests-and-integration-tests"><a class="anchor" href="#bonus-building-a-consolidated-report-for-unit-tests-and-integration-tests"></a>10. Bonus: Building a consolidated report for Unit Tests and Integration Tests</h2>
<div class="sectionbody">
<div class="paragraph">
<p>So, finally, let&#8217;s improve the setup even further and let&#8217;s merge the two execution files (<strong>jacoco-ut.exec</strong> and <strong>jacoco-it.exec</strong>) into one consolidated report and generate a consolidated report that will show the coverage of all your tests combined.</p>
</div>
<div class="paragraph">
<p>You should end up with something like this (note the addition of the <code>merge-results</code> and <code>post-merge-report</code> executions):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="xml" class="language-xml hljs">&lt;project&gt;
    ...
    &lt;build&gt;
        &lt;plugins&gt;
            &lt;plugin&gt;
                &lt;artifactId&gt;maven-surefire-plugin&lt;/artifactId&gt;
                &lt;version&gt;${surefire-plugin.version}&lt;/version&gt;
                &lt;configuration&gt;
                    &lt;excludedGroups&gt;integration&lt;/excludedGroups&gt;
                    &lt;systemPropertyVariables&gt;
                        &lt;jacoco-agent.destfile&gt;${project.build.directory}/jacoco-ut.exec&lt;/jacoco-agent.destfile&gt;
                        &lt;java.util.logging.manager&gt;org.jboss.logmanager.LogManager&lt;/java.util.logging.manager&gt;
                        &lt;maven.home&gt;${maven.home}&lt;/maven.home&gt;
                    &lt;/systemPropertyVariables&gt;
                &lt;/configuration&gt;
                &lt;executions&gt;
                    &lt;execution&gt;
                        &lt;id&gt;integration-tests&lt;/id&gt;
                        &lt;phase&gt;integration-test&lt;/phase&gt;
                        &lt;goals&gt;
                            &lt;goal&gt;test&lt;/goal&gt;
                        &lt;/goals&gt;
                        &lt;configuration&gt;
                            &lt;excludedGroups&gt;!integration&lt;/excludedGroups&gt;
                            &lt;groups&gt;integration&lt;/groups&gt;
                            &lt;systemPropertyVariables&gt;
                                &lt;jacoco-agent.destfile&gt;${project.build.directory}/jacoco-it.exec&lt;/jacoco-agent.destfile&gt;
                            &lt;/systemPropertyVariables&gt;
                        &lt;/configuration&gt;
                    &lt;/execution&gt;
                &lt;/executions&gt;
            &lt;/plugin&gt;
            ...
            &lt;plugin&gt;
                &lt;groupId&gt;org.jacoco&lt;/groupId&gt;
                &lt;artifactId&gt;jacoco-maven-plugin&lt;/artifactId&gt;
                &lt;version&gt;${jacoco.version}&lt;/version&gt;
                &lt;executions&gt;
                    &lt;execution&gt;
                        &lt;id&gt;instrument-ut&lt;/id&gt;
                        &lt;goals&gt;
                            &lt;goal&gt;instrument&lt;/goal&gt;
                        &lt;/goals&gt;
                    &lt;/execution&gt;
                    &lt;execution&gt;
                        &lt;id&gt;restore-ut&lt;/id&gt;
                        &lt;goals&gt;
                            &lt;goal&gt;restore-instrumented-classes&lt;/goal&gt;
                        &lt;/goals&gt;
                    &lt;/execution&gt;
                    &lt;execution&gt;
                        &lt;id&gt;report-ut&lt;/id&gt;
                        &lt;goals&gt;
                            &lt;goal&gt;report&lt;/goal&gt;
                        &lt;/goals&gt;
                        &lt;configuration&gt;
                            &lt;dataFile&gt;${project.build.directory}/jacoco-ut.exec&lt;/dataFile&gt;
                            &lt;outputDirectory&gt;${project.reporting.outputDirectory}/jacoco-ut&lt;/outputDirectory&gt;
                        &lt;/configuration&gt;
                    &lt;/execution&gt;
                    &lt;execution&gt;
                        &lt;id&gt;instrument-it&lt;/id&gt;
                        &lt;phase&gt;pre-integration-test&lt;/phase&gt;
                        &lt;goals&gt;
                            &lt;goal&gt;instrument&lt;/goal&gt;
                        &lt;/goals&gt;
                    &lt;/execution&gt;
                    &lt;execution&gt;
                        &lt;id&gt;restore-it&lt;/id&gt;
                        &lt;phase&gt;post-integration-test&lt;/phase&gt;
                        &lt;goals&gt;
                            &lt;goal&gt;restore-instrumented-classes&lt;/goal&gt;
                        &lt;/goals&gt;
                    &lt;/execution&gt;
                    &lt;execution&gt;
                        &lt;id&gt;report-it&lt;/id&gt;
                        &lt;phase&gt;post-integration-test&lt;/phase&gt;
                        &lt;goals&gt;
                            &lt;goal&gt;report&lt;/goal&gt;
                        &lt;/goals&gt;
                        &lt;configuration&gt;
                            &lt;dataFile&gt;${project.build.directory}/jacoco-it.exec&lt;/dataFile&gt;
                            &lt;outputDirectory&gt;${project.reporting.outputDirectory}/jacoco-it&lt;/outputDirectory&gt;
                        &lt;/configuration&gt;
                    &lt;/execution&gt;
                    &lt;execution&gt;
                        &lt;id&gt;merge-results&lt;/id&gt;
                        &lt;phase&gt;verify&lt;/phase&gt;
                        &lt;goals&gt;
                            &lt;goal&gt;merge&lt;/goal&gt;
                        &lt;/goals&gt;
                        &lt;configuration&gt;
                            &lt;fileSets&gt;
                                &lt;fileSet&gt;
                                    &lt;directory&gt;${project.build.directory}&lt;/directory&gt;
                                    &lt;includes&gt;
                                        &lt;include&gt;*.exec&lt;/include&gt;
                                    &lt;/includes&gt;
                                &lt;/fileSet&gt;
                            &lt;/fileSets&gt;
                            &lt;destFile&gt;${project.build.directory}/jacoco.exec&lt;/destFile&gt;
                        &lt;/configuration&gt;
                    &lt;/execution&gt;
                    &lt;execution&gt;
                        &lt;id&gt;post-merge-report&lt;/id&gt;
                        &lt;phase&gt;verify&lt;/phase&gt;
                        &lt;goals&gt;
                            &lt;goal&gt;report&lt;/goal&gt;
                        &lt;/goals&gt;
                        &lt;configuration&gt;
                            &lt;dataFile&gt;${project.build.directory}/jacoco.exec&lt;/dataFile&gt;
                            &lt;outputDirectory&gt;${project.reporting.outputDirectory}/jacoco&lt;/outputDirectory&gt;
                        &lt;/configuration&gt;
                    &lt;/execution&gt;
                &lt;/executions&gt;
            &lt;/plugin&gt;
        &lt;/plugins&gt;
    &lt;/build&gt;
    ...
    &lt;dependencies&gt;
        ...
        &lt;dependency&gt;
            &lt;groupId&gt;org.jacoco&lt;/groupId&gt;
            &lt;artifactId&gt;org.jacoco.agent&lt;/artifactId&gt;
            &lt;classifier&gt;runtime&lt;/classifier&gt;
            &lt;scope&gt;test&lt;/scope&gt;
            &lt;version&gt;${jacoco.version}&lt;/version&gt;
        &lt;/dependency&gt;
    &lt;/dependencies&gt;
&lt;/project&gt;</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="conclusion"><a class="anchor" href="#conclusion"></a>11. Conclusion</h2>
<div class="sectionbody">
<div class="paragraph">
<p>You now have all the information you need to study the coverage of your tests!
But remember, some code that is not covered is certinaly not well tested. But some code that is covered is not necessarily <strong>well</strong> tested. Make sure to write good tests!</p>
</div>
</div>
</div>
    </div>
  </div>
</div>

  </div>

  <div class="content project-footer">
  <div class="footer-section">
    <div class="logo-wrapper">
      <a href="/"><img src="/assets/images/quarkus_logo_horizontal_rgb_reverse.svg" class="project-logo" title="Quarkus"></a>
    </div>
  </div>
  <div class="grid-wrapper">
    <p class="grid__item width-3-12">Quarkus is open. All dependencies of this project are available under the <a href='https://www.apache.org/licenses/LICENSE-2.0' target='_blank'>Apache Software License 2.0</a> or compatible license.<br /><br />This website was built with <a href='https://jekyllrb.com/' target='_blank'>Jekyll</a>, is hosted on <a href='https://pages.github.com/' target='_blank'>Github Pages</a> and is completely open source. If you want to make it better, <a href='https://github.com/quarkusio/quarkusio.github.io' target='_blank'>fork the website</a> and show us what you’ve got.</p>

    
      <div class="width-1-12 project-links">
        <span>Navigation</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="/">Home</a></li>
          
            <li><a href="/guides">Guides</a></li>
          
            <li><a href="/community/#contributing">Contribute</a></li>
          
            <li><a href="/faq">FAQ</a></li>
          
            <li><a href="/get-started">Get Started</a></li>
          
        </ul>
      </div>
    
      <div class="width-1-12 project-links">
        <span>Contribute</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="https://twitter.com/quarkusio">Follow us</a></li>
          
            <li><a href="https://github.com/quarkusio">GitHub</a></li>
          
            <li><a href="/security">Security&nbsp;policy</a></li>
          
        </ul>
      </div>
    
      <div class="width-1-12 project-links">
        <span>Get Help</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="https://groups.google.com/forum/#!forum/quarkus-dev">Forums</a></li>
          
            <li><a href="https://quarkusio.zulipchat.com">Chatroom</a></li>
          
        </ul>
      </div>
    

    
      <div class="width-3-12 more-links">
        <span>Quarkus is made of community projects</span>
        <ul class="footer-links">
          
            <li><a href="https://vertx.io/" target="_blank">Eclipse Vert.x</a></li>
          
            <li><a href="https://microprofile.io" target="_blank">Eclipse MicroProfile</a></li>
          
            <li><a href="https://hibernate.org" target="_blank">Hibernate</a></li>
          
            <li><a href="https://netty.io" target="_blank">Netty</a></li>
          
            <li><a href="https://resteasy.github.io" target="_blank">RESTEasy</a></li>
          
            <li><a href="https://camel.apache.org" target="_blank">Apache Camel</a></li>
          
            <li><a href="https://code.quarkus.io/" target="_blank">And many more...</a></li>
          
        </ul>
      </div>
    
  </div>
</div>
  <div class="content redhat-footer">
  <div class="grid-wrapper">
    <span class="licence">
      <i class="fab fa-creative-commons"></i><i class="fab fa-creative-commons-by"></i> <a href="https://creativecommons.org/licenses/by/3.0/" target="_blank">CC by 3.0</a> | <a href="https://www.redhat.com/en/about/privacy-policy">Privacy Policy</a>
    </span>
    <span class="redhat">
      Sponsored by
    </span>
    <span class="redhat-logo">
      <a href="https://www.redhat.com/" target="_blank"><img src="/assets/images/redhat_reversed.svg"></a>
    </span>
  </div>
</div>


  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js" integrity="sha384-8gBf6Y4YYq7Jx97PIqmTwLPin4hxIzQw5aDmUg/DDhul9fFpbbLcLh3nTIIDJKhx" crossorigin="anonymous"></script>
  <script type="text/javascript" src="/assets/javascript/mobile-nav.js"></script>
  <script type="text/javascript" src="/assets/javascript/scroll-down.js"></script>
  <script src="/assets/javascript/satellite.js" type="text/javascript"></script>
  <script src="https://quarkus.io/guides/javascript/config.js" type="text/javascript"></script>
  <script src="/assets/javascript/search-filter.js" type="text/javascript"></script>
  <script src="/assets/javascript/back-to-top.js" type="text/javascript"></script>
</body>

</html>
